package crmdna.common;

import crmdna.common.APIResponse.Status;

public class UnitUtils {

	public enum PhysicalQuantity {
		WEIGHT, VOLUME, NUMBER
	}

	public enum ReportingUnit {
		KG, GRAM, ML, LITRE, NUMBER
	}

	public static double safeGetQuantityInReportingUnit(
			PhysicalQuantity physicalQuantity, double quantityInDefaultUnit,
			ReportingUnit reportingUnit) {

		if (physicalQuantity == PhysicalQuantity.WEIGHT) {
			if (reportingUnit == ReportingUnit.KG)
				return quantityInDefaultUnit * 1000;
			else if (reportingUnit == ReportingUnit.GRAM)
				return quantityInDefaultUnit;
			else {
				// should never come here
				throw new APIException()
						.status(Status.ERROR_RESOURCE_INCORRECT).message(
								"Invalid reporting unit [" + reportingUnit
										+ "] for physical quantity ["
										+ physicalQuantity + "]");
			}
		}

		if (physicalQuantity == PhysicalQuantity.VOLUME) {
			if (reportingUnit == ReportingUnit.LITRE)
				return quantityInDefaultUnit * 1000;

			if (reportingUnit == ReportingUnit.ML)
				return quantityInDefaultUnit;

			throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT)
					.message(
							"Invalid reporting unit [" + reportingUnit
									+ "] for physical quantity ["
									+ physicalQuantity + "]");
		}

		if (physicalQuantity == PhysicalQuantity.NUMBER)
			return quantityInDefaultUnit;

		throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT)
				.message(
						"Unsupported physical quantity [" + physicalQuantity
								+ "]");
	}

	public static double safeGetQuantityInDefaultUnit(
			PhysicalQuantity physicalQuantity, double quantityInReportingUnit,
			ReportingUnit reportingUnit) {

		if (physicalQuantity == PhysicalQuantity.WEIGHT) {
			if (reportingUnit == ReportingUnit.KG)
				return quantityInReportingUnit / 1000;
			else if (reportingUnit == ReportingUnit.GRAM)
				return quantityInReportingUnit;
			else {
				// should never come here
				throw new APIException()
						.status(Status.ERROR_RESOURCE_INCORRECT).message(
								"Invalid reporting unit [" + reportingUnit
										+ "] for physical quantity ["
										+ physicalQuantity + "]");
			}
		}

		if (physicalQuantity == PhysicalQuantity.VOLUME) {
			if (reportingUnit == ReportingUnit.LITRE)
				return quantityInReportingUnit / 1000;

			if (reportingUnit == ReportingUnit.ML)
				return quantityInReportingUnit;

			throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT)
					.message(
							"Invalid reporting unit [" + reportingUnit
									+ "] for physical quantity ["
									+ physicalQuantity + "]");
		}

		if (physicalQuantity == PhysicalQuantity.NUMBER)
			return quantityInReportingUnit;

		throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT)
				.message(
						"Unsupported physical quantity [" + physicalQuantity
								+ "]");
	}

	static void ensureValidReportingUnit(PhysicalQuantity physicalQuantity,
			ReportingUnit reportingUnit) {

		boolean invalid = false;
		if (physicalQuantity == PhysicalQuantity.WEIGHT) {
			if ((reportingUnit != ReportingUnit.GRAM)
					&& (reportingUnit != ReportingUnit.KG))
				invalid = true;
		} else if (physicalQuantity == PhysicalQuantity.VOLUME) {
			if ((reportingUnit != ReportingUnit.LITRE)
					&& (reportingUnit != ReportingUnit.ML))
				invalid = true;
		} else if (physicalQuantity == PhysicalQuantity.NUMBER) {
			if (reportingUnit != ReportingUnit.NUMBER)
				invalid = true;
		}

		if (invalid)
			throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT)
					.message(
							"Invalid reporting unit [" + reportingUnit
									+ "] for physical quantity ["
									+ physicalQuantity + "]");
	}
}
